/**
 * 
 */
package edu.fiu.cs.kdrg.sql.syntax.tree;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import net.sf.jsqlparser.expression.AllComparisonExpression;
import net.sf.jsqlparser.expression.AnyComparisonExpression;
import net.sf.jsqlparser.expression.CaseExpression;
import net.sf.jsqlparser.expression.DateValue;
import net.sf.jsqlparser.expression.DoubleValue;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.InverseExpression;
import net.sf.jsqlparser.expression.JdbcParameter;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.NullValue;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.TimeValue;
import net.sf.jsqlparser.expression.TimestampValue;
import net.sf.jsqlparser.expression.WhenClause;
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseOr;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseXor;
import net.sf.jsqlparser.expression.operators.arithmetic.Concat;
import net.sf.jsqlparser.expression.operators.arithmetic.Division;
import net.sf.jsqlparser.expression.operators.arithmetic.Multiplication;
import net.sf.jsqlparser.expression.operators.arithmetic.Subtraction;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.Between;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.GreaterThan;
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor;
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
import net.sf.jsqlparser.expression.operators.relational.Matches;
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.StatementVisitor;
import net.sf.jsqlparser.statement.create.table.ColumnDefinition;
import net.sf.jsqlparser.statement.create.table.CreateTable;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.drop.Drop;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.replace.Replace;
import net.sf.jsqlparser.statement.select.AllColumns;
import net.sf.jsqlparser.statement.select.AllTableColumns;
import net.sf.jsqlparser.statement.select.FromItemVisitor;
import net.sf.jsqlparser.statement.select.IntoTableVisitor;
import net.sf.jsqlparser.statement.select.Join;
import net.sf.jsqlparser.statement.select.Limit;
import net.sf.jsqlparser.statement.select.OrderByElement;
import net.sf.jsqlparser.statement.select.OrderByVisitor;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectExpressionItem;
import net.sf.jsqlparser.statement.select.SelectItem;
import net.sf.jsqlparser.statement.select.SelectItemVisitor;
import net.sf.jsqlparser.statement.select.SelectVisitor;
import net.sf.jsqlparser.statement.select.SubJoin;
import net.sf.jsqlparser.statement.select.SubSelect;
import net.sf.jsqlparser.statement.select.Union;
import net.sf.jsqlparser.statement.truncate.Truncate;
import net.sf.jsqlparser.statement.update.Update;

/**
 * @author Chunqiu Zeng
 * 
 */

public class SyntaxTreeVisitor implements ExpressionVisitor, ItemsListVisitor,
		StatementVisitor, FromItemVisitor, IntoTableVisitor, SelectItemVisitor,
		SelectVisitor, OrderByVisitor {

	private List<String> tables = new ArrayList<String>();

	private List<String> columns = new ArrayList<String>();

	@Override
	public void visit(OrderByElement orderBy) {
		// TODO Auto-generated method stub
		orderBy.getExpression();
	}

	@Override
	public void visit(PlainSelect plainSelect) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Union union) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(AllColumns allColumns) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(AllTableColumns allTableColumns) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(SelectExpressionItem selectExpressionItem) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Table tableName) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(SubJoin subjoin) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Select select) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Delete delete) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Update update) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Insert insert) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Replace replace) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Drop drop) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Truncate truncate) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(CreateTable createTable) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(ExpressionList expressionList) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(NullValue nullValue) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Function function) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(InverseExpression inverseExpression) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(JdbcParameter jdbcParameter) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(DoubleValue doubleValue) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(LongValue longValue) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(DateValue dateValue) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(TimeValue timeValue) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(TimestampValue timestampValue) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Parenthesis parenthesis) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(StringValue stringValue) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Addition addition) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Division division) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Multiplication multiplication) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Subtraction subtraction) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(AndExpression andExpression) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(OrExpression orExpression) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Between between) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(EqualsTo equalsTo) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(GreaterThan greaterThan) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(GreaterThanEquals greaterThanEquals) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(InExpression inExpression) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(IsNullExpression isNullExpression) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(LikeExpression likeExpression) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(MinorThan minorThan) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(MinorThanEquals minorThanEquals) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(NotEqualsTo notEqualsTo) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Column tableColumn) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(SubSelect subSelect) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(CaseExpression caseExpression) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(WhenClause whenClause) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(ExistsExpression existsExpression) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(AllComparisonExpression allComparisonExpression) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(AnyComparisonExpression anyComparisonExpression) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Concat concat) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(Matches matches) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(BitwiseAnd bitwiseAnd) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(BitwiseOr bitwiseOr) {
		// TODO Auto-generated method stub

	}

	@Override
	public void visit(BitwiseXor bitwiseXor) {
		// TODO Auto-generated method stub

	}

	@Override
	public Node nodeVisit(NullValue nullValue) {
		// TODO Auto-generated method stub
		Node node = new Node("NULL", NodeType.VALUE);
		return node;
	}

	@Override
	public Node nodeVisit(Function function) {
		// TODO Auto-generated method stub
		Node node = new Node(function.getName(), NodeType.FUNCTION);
		if (function.getParameters() != null)
			node.addChild(function.getParameters().nodeAccept(this));
		if(function.isAllColumns()){
			Node expNode = new Node("expressionList",NodeType.EXPLIST);
			Node starNode = new Node("*",NodeType.EXP);
			expNode.addChild(starNode);
			node.addChild(expNode);
		}
		return node;
	}

	@Override
	public Node nodeVisit(InverseExpression inverseExpression) {
		// TODO Auto-generated method stub
		Node inv = new Node("inverse", NodeType.EXP);
		inv.addChild(inverseExpression.getExpression().nodeAccept(this));
		return inv;
	}

	@Override
	public Node nodeVisit(JdbcParameter jdbcParameter) {
		// TODO Auto-generated method stub
		Node node = new Node("param", NodeType.EXP);
		return node;
	}

	@Override
	public Node nodeVisit(DoubleValue doubleValue) {
		// TODO Auto-generated method stub
		Node node = new Node(doubleValue.toString(), NodeType.VALUE);
		return node;
	}

	@Override
	public Node nodeVisit(LongValue longValue) {
		// TODO Auto-generated method stub
		Node node = new Node(longValue.toString(), NodeType.VALUE);
		return node;
	}

	@Override
	public Node nodeVisit(DateValue dateValue) {
		// TODO Auto-generated method stub
		Node node = new Node(dateValue.toString(), NodeType.VALUE);
		return node;
	}

	@Override
	public Node nodeVisit(TimeValue timeValue) {
		// TODO Auto-generated method stub
		Node node = new Node(timeValue.toString(), NodeType.VALUE);
		return node;
	}

	@Override
	public Node nodeVisit(TimestampValue timestampValue) {
		// TODO Auto-generated method stub
		Node node = new Node(timestampValue.toString(), NodeType.VALUE);
		return node;
	}

	@Override
	public Node nodeVisit(Parenthesis parenthesis) {
		// TODO Auto-generated method stub
		if (!parenthesis.isNot())
			return parenthesis.nodeAccept(this);
		else {
			Node node = new Node("not", NodeType.EXP);
			node.addChild(parenthesis.nodeAccept(this));
			return node;
		}
	}

	@Override
	public Node nodeVisit(StringValue stringValue) {
		// TODO Auto-generated method stub
		Node node = new Node(stringValue.toString(), NodeType.VALUE);
		return node;
	}

	@Override
	public Node nodeVisit(Addition addition) {
		// TODO Auto-generated method stub
		Expression left = addition.getLeftExpression();
		Expression right = addition.getRightExpression();
		Node node = new Node("addition", NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		if (!addition.isNot())
			return node;
		else {
			Node notExp = new Node("not", NodeType.EXP);
			notExp.addChild(node);
			return notExp;
		}
	}

	@Override
	public Node nodeVisit(Division division) {
		// TODO Auto-generated method stub
		Expression left = division.getLeftExpression();
		Expression right = division.getRightExpression();
		Node node = new Node("division", NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		if (!division.isNot())
			return node;
		else {
			Node notExp = new Node("not", NodeType.EXP);
			notExp.addChild(node);
			return notExp;
		}
	}

	@Override
	public Node nodeVisit(Multiplication multiplication) {
		// TODO Auto-generated method stub
		Expression left = multiplication.getLeftExpression();
		Expression right = multiplication.getRightExpression();
		Node node = new Node("multiplication", NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		if (!multiplication.isNot())
			return node;
		else {
			Node notExp = new Node("not", NodeType.EXP);
			notExp.addChild(node);
			return notExp;
		}
	}

	@Override
	public Node nodeVisit(Subtraction subtraction) {
		// TODO Auto-generated method stub
		Expression left = subtraction.getLeftExpression();
		Expression right = subtraction.getRightExpression();
		Node node = new Node("subtraction", NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		if (!subtraction.isNot())
			return node;
		else {
			Node notExp = new Node("not", NodeType.EXP);
			notExp.addChild(node);
			return notExp;
		}
	}

	@Override
	public Node nodeVisit(AndExpression andExpression) {
		// TODO Auto-generated method stub
		Expression left = andExpression.getLeftExpression();
		Expression right = andExpression.getRightExpression();
		Node node = new Node("andExpression", NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		if (!andExpression.isNot())
			return node;
		else {
			Node notExp = new Node("not", NodeType.EXP);
			notExp.addChild(node);
			return notExp;
		}
	}

	@Override
	public Node nodeVisit(OrExpression orExpression) {
		// TODO Auto-generated method stub
		Expression left = orExpression.getLeftExpression();
		Expression right = orExpression.getRightExpression();
		Node node = new Node("orExpression", NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		if (!orExpression.isNot())
			return node;
		else {
			Node notExp = new Node("not", NodeType.EXP);
			notExp.addChild(node);
			return notExp;
		}
	}

	@Override
	public Node nodeVisit(Between between) {
		// TODO Auto-generated method stub
		Expression left = between.getLeftExpression();
		Expression start = between.getBetweenExpressionStart();
		Expression end = between.getBetweenExpressionEnd();
		String name = between.isNot() ? "not between" : "between";
		Node node = new Node(name, NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(start.nodeAccept(this));
		node.addChild(end.nodeAccept(this));
		return node;
	}

	@Override
	public Node nodeVisit(EqualsTo equalsTo) {
		// TODO Auto-generated method stub
		Expression left = equalsTo.getLeftExpression();
		Expression right = equalsTo.getRightExpression();
		Node node = new Node("equalTo", NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		if (!equalsTo.isNot())
			return node;
		else {
			Node notExp = new Node("not", NodeType.EXP);
			notExp.addChild(node);
			return notExp;
		}
	}

	@Override
	public Node nodeVisit(GreaterThan greaterThan) {
		// TODO Auto-generated method stub
		Expression left = greaterThan.getLeftExpression();
		Expression right = greaterThan.getRightExpression();
		Node node = new Node("greaterThan", NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		if (!greaterThan.isNot())
			return node;
		else {
			Node notExp = new Node("not", NodeType.EXP);
			notExp.addChild(node);
			return notExp;
		}
	}

	@Override
	public Node nodeVisit(GreaterThanEquals greaterThanEquals) {
		// TODO Auto-generated method stub
		Expression left = greaterThanEquals.getLeftExpression();
		Expression right = greaterThanEquals.getRightExpression();
		Node node = new Node("greaterThanEquals", NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		if (!greaterThanEquals.isNot())
			return node;
		else {
			Node notExp = new Node("not", NodeType.EXP);
			notExp.addChild(node);
			return notExp;
		}
	}

	@Override
	public Node nodeVisit(InExpression inExpression) {
		// TODO Auto-generated method stub
		String name = inExpression.isNot() ? "not in" : "in";
		Node node = new Node(name, NodeType.EXP);
		Expression left = inExpression.getLeftExpression();
		ItemsList items = inExpression.getItemsList();
		node.addChild(left.nodeAccept(this));
		node.addChild(items.nodeAccept(this));
		return node;
	}

	@Override
	public Node nodeVisit(IsNullExpression isNullExpression) {
		// TODO Auto-generated method stub
		String name = isNullExpression.isNot() ? "not null" : "null";
		Node node = new Node(name, NodeType.EXP);
		node.addChild(isNullExpression.getLeftExpression().nodeAccept(this));
		return node;
	}

	@Override
	public Node nodeVisit(LikeExpression likeExpression) {
		// TODO Auto-generated method stub
		String name = likeExpression.isNot() ? "not like" : "like";
		Node node = new Node(name, NodeType.EXP);
		Expression left = likeExpression.getLeftExpression();
		Expression right = likeExpression.getRightExpression();
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		return node;
	}

	@Override
	public Node nodeVisit(MinorThan minorThan) {
		// TODO Auto-generated method stub
		Expression left = minorThan.getLeftExpression();
		Expression right = minorThan.getRightExpression();
		Node node = new Node("minorThan", NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		if (!minorThan.isNot())
			return node;
		else {
			Node notExp = new Node("not", NodeType.EXP);
			notExp.addChild(node);
			return notExp;
		}
	}

	@Override
	public Node nodeVisit(MinorThanEquals minorThanEquals) {
		// TODO Auto-generated method stub
		Expression left = minorThanEquals.getLeftExpression();
		Expression right = minorThanEquals.getRightExpression();
		Node node = new Node("minorThanEquals", NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		if (!minorThanEquals.isNot())
			return node;
		else {
			Node notExp = new Node("not", NodeType.EXP);
			notExp.addChild(node);
			return notExp;
		}
	}

	@Override
	public Node nodeVisit(NotEqualsTo notEqualsTo) {
		// TODO Auto-generated method stub
		Expression left = notEqualsTo.getLeftExpression();
		Expression right = notEqualsTo.getRightExpression();
		Node node = new Node("notEqualsTo", NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		if (!notEqualsTo.isNot())
			return node;
		else {
			Node notExp = new Node("not", NodeType.EXP);
			notExp.addChild(node);
			return notExp;
		}
	}

	@Override
	public Node nodeVisit(Column tableColumn) {
		// TODO Auto-generated method stub
		String colName = tableColumn.getWholeColumnName();
		Node node = new Node(colName, NodeType.COLUMN);
		return node;
	}

	@Override
	public Node nodeVisit(SubSelect subSelect) {
		// TODO Auto-generated method stub
		return subSelect.getSelectBody().nodeAccept(this);
	}

	@Override
	public Node nodeVisit(CaseExpression caseExpression) {
		// TODO Auto-generated method stub
		Node node = new Node("switch", NodeType.EXP);
		if (caseExpression.getSwitchExpression() != null)
			node.addChild(caseExpression.getSwitchExpression().nodeAccept(this));
		List cases = caseExpression.getWhenClauses();
		for (int i = 0; i < cases.size(); i++) {
			WhenClause cse = (WhenClause) cases.get(i);
			node.addChild(cse.nodeAccept(this));
		}
		Expression els = caseExpression.getElseExpression();
		if (els != null)
			node.addChild(els.nodeAccept(this));
		return node;
	}

	@Override
	public Node nodeVisit(WhenClause whenClause) {
		// TODO Auto-generated method stub
		Node node = new Node("whenThen", NodeType.EXP);
		node.addChild(whenClause.getWhenExpression().nodeAccept(this));
		node.addChild(whenClause.getThenExpression().nodeAccept(this));
		return node;
	}

	@Override
	public Node nodeVisit(ExistsExpression existsExpression) {
		// TODO Auto-generated method stub
		String name = existsExpression.isNot() ? "not exists" : "exists";
		Node node = new Node(name, NodeType.EXP);
		node.addChild(existsExpression.getRightExpression().nodeAccept(this));
		return node;
	}

	@Override
	public Node nodeVisit(AllComparisonExpression allComparisonExpression) {
		// TODO Auto-generated method stub
		Node node = new Node("ALL", NodeType.EXP);
		node.addChild(allComparisonExpression.GetSubSelect().getSelectBody()
				.nodeAccept(this));
		return node;
	}

	@Override
	public Node nodeVisit(AnyComparisonExpression anyComparisonExpression) {
		// TODO Auto-generated method stub
		Node node = new Node("ANY", NodeType.EXP);
		node.addChild(anyComparisonExpression.GetSubSelect().getSelectBody()
				.nodeAccept(this));
		return node;
	}

	@Override
	public Node nodeVisit(Concat concat) {
		// TODO Auto-generated method stub
		Expression left = concat.getLeftExpression();
		Expression right = concat.getRightExpression();
		Node node = new Node("concat", NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		if (!concat.isNot())
			return node;
		else {
			Node notExp = new Node("not", NodeType.EXP);
			notExp.addChild(node);
			return notExp;
		}

	}

	@Override
	public Node nodeVisit(Matches matches) {
		// TODO Auto-generated method stub
		Expression left = matches.getLeftExpression();
		Expression right = matches.getRightExpression();
		Node node = new Node("matches", NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		if (!matches.isNot())
			return node;
		else {
			Node notExp = new Node("not", NodeType.EXP);
			notExp.addChild(node);
			return notExp;
		}
	}

	@Override
	public Node nodeVisit(BitwiseAnd bitwiseAnd) {
		// TODO Auto-generated method stub
		Expression left = bitwiseAnd.getLeftExpression();
		Expression right = bitwiseAnd.getRightExpression();
		Node node = new Node("bitwiseAnd", NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		if (!bitwiseAnd.isNot())
			return node;
		else {
			Node notExp = new Node("not", NodeType.EXP);
			notExp.addChild(node);
			return notExp;
		}
	}

	@Override
	public Node nodeVisit(BitwiseOr bitwiseOr) {
		// TODO Auto-generated method stub
		Expression left = bitwiseOr.getLeftExpression();
		Expression right = bitwiseOr.getRightExpression();
		Node node = new Node("bitwiseOr", NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		if (!bitwiseOr.isNot())
			return node;
		else {
			Node notExp = new Node("not", NodeType.EXP);
			notExp.addChild(node);
			return notExp;
		}
	}

	@Override
	public Node nodeVisit(BitwiseXor bitwiseXor) {
		// TODO Auto-generated method stub
		Expression left = bitwiseXor.getLeftExpression();
		Expression right = bitwiseXor.getRightExpression();
		Node node = new Node("bitwiseXor", NodeType.EXP);
		node.addChild(left.nodeAccept(this));
		node.addChild(right.nodeAccept(this));
		if (!bitwiseXor.isNot())
			return node;
		else {
			Node notExp = new Node("not", NodeType.EXP);
			notExp.addChild(node);
			return notExp;
		}
	}

	@Override
	public Node nodeVisit(ExpressionList expressionList) {
		// TODO Auto-generated method stub
		Node node = new Node("expressionList", NodeType.EXPLIST);
		List explist = expressionList.getExpressions();
		for (int i = 0; i < explist.size(); i++) {
			Expression e = (Expression) explist.get(i);
			node.addChild(e.nodeAccept(this));
		}
		return node;
	}

	@Override
	public Node nodeVisit(Select select) {
		// TODO Auto-generated method stub
		return select.getSelectBody().nodeAccept(this);
	}

	@Override
	public Node nodeVisit(Delete delete) {
		// TODO Auto-generated method stub
		Node node = new Node("DELETE", NodeType.STMT);
		Node del = new Node("delete", NodeType.DELETE_STATEMENT);
		node.addChild(del);

		// from items
		Node from = new Node("from", NodeType.FROM_ITEM);
		Node fromItem = delete.getTable().nodeAccept(this);
		from.addChild(fromItem);
		node.addChild(from);

		if (delete.getWhere() != null) {
			Node where = new Node("where", NodeType.WHERE_CLAUSE);
			Node expression = delete.getWhere().nodeAccept(this);
			where.addChild(expression);
			node.addChild(where);
		}

		return node;
	}

	@Override
	public Node nodeVisit(Update update) {
		Node node = new Node("UPDATE", NodeType.STMT);
		Node updt = new Node("update", NodeType.UPDATE_STATEMENT);
		node.addChild(updt);
		updt.addChild(update.getTable().nodeAccept(this));

		List cols = update.getColumns();
		List vals = update.getExpressions();
		for (int i = 0; i < cols.size(); i++) {
			Column c = (Column) cols.get(i);
			Expression v = (Expression) vals.get(i);
			Node s = new Node("set", NodeType.SET);
			s.addChild(c.nodeAccept(this));
			s.addChild(v.nodeAccept(this));
			node.addChild(s);
		}

		if (update.getWhere() != null) {
			Node where = new Node("where", NodeType.WHERE_CLAUSE);
			Node expression = update.getWhere().nodeAccept(this);
			where.addChild(expression);
			node.addChild(where);
		}
		// TODO Auto-generated method stub
		return node;
	}

	@Override
	public Node nodeVisit(Insert insert) {
		// TODO Auto-generated method stub
		Node node = new Node("INSERT", NodeType.STMT);
		Node inst = new Node("insert", NodeType.INSERT_STATEMENT);
		node.addChild(inst);
		inst.addChild(insert.getTable().nodeAccept(this));

		List cols = insert.getColumns();
		Node columList = new Node("columnList", NodeType.COLUMN_LIST);
		for (int i = 0; i < cols.size(); i++) {
			Column c = (Column) cols.get(i);

			columList.addChild(c.nodeAccept(this));
		}
		node.addChild(columList);

		node.addChild(insert.getItemsList().nodeAccept(this));

		return node;
	}

	@Override
	public Node nodeVisit(Replace replace) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Node nodeVisit(Drop drop) {
		// TODO Auto-generated method stub
		Node node = new Node("DROP", NodeType.STMT);
		Node drp = new Node("drop", NodeType.DROP_STATEMENT);

		Node obj = new Node(drop.getName(), NodeType.TABLE);
		drp.addChild(obj);
		node.addChild(drp);
		return node;
	}

	@Override
	public Node nodeVisit(Truncate truncate) {
		// TODO Auto-generated method stub
		Node node = new Node("TRUNCATE", NodeType.STMT);
		Node trct = new Node("truncate", NodeType.TRUNCATE_STATEMENT);
		Node obj = truncate.getTable().nodeAccept(this);
		trct.addChild(obj);
		node.addChild(trct);
		return node;
	}

	@Override
	public Node nodeVisit(CreateTable createTable) {
		// TODO Auto-generated method stub
		Node node = new Node("CREATE", NodeType.STMT);
		Node cret = new Node("create", NodeType.CREATE_STATEMENT);
		cret.addChild(createTable.getTable().nodeAccept(this));
		node.addChild(cret);

		List defs = createTable.getColumnDefinitions();
		for (int i = 0; i < defs.size(); i++) {
			ColumnDefinition def = (ColumnDefinition) defs.get(i);
			Node cd = new Node(def.getColumnName(), NodeType.COLUMN);
			Node type = new Node(def.getColDataType().getDataType(),
					NodeType.TYPE);
			cd.addChild(type);
			node.addChild(cd);
		}
		return node;
	}

	@Override
	public Node nodeVisit(Table tableName) {
		// TODO Auto-generated method stub

		return new Node(tableName.getName(), NodeType.TABLE);
	}

	@Override
	public Node nodeVisit(SubJoin subjoin) {
		// TODO Auto-generated method stub
		// Node node = new Node("join",NodeType.FROM_ITEM);
		// node.addChild(subjoin.getLeft().nodeAccept(this));
		// node.addChild(subjoin.getJoin());
		return null;
	}

	@Override
	public Node nodeVisit(AllColumns allColumns) {
		// TODO Auto-generated method stub
		Node node = new Node(allColumns.toString(), NodeType.COLUMN);
		return node;
	}

	@Override
	public Node nodeVisit(AllTableColumns allTableColumns) {
		// TODO Auto-generated method stub
		Node node = new Node(allTableColumns.toString(), NodeType.COLUMN);
		return node;
	}

	@Override
	public Node nodeVisit(SelectExpressionItem selectExpressionItem) {
		// TODO Auto-generated method stub
		return selectExpressionItem.getExpression().nodeAccept(this);
	}

	@Override
	public Node nodeVisit(PlainSelect plainSelect) {

		Node node = new Node("QUERY", NodeType.STMT);

		// TODO Auto-generated method stub
		Node select = new Node("select", NodeType.SELECT_STATEMENT);
		// column list
		List selectItems = plainSelect.getSelectItems();
		Node columnList = new Node("columns", NodeType.COLUMN_LIST);
		for (int i = 0; i < selectItems.size(); i++) {
			SelectItem item = (SelectItem) selectItems.get(i);
			columnList.addChild(item.nodeAccept(this));
		}
		select.addChild(columnList);
		node.addChild(select);
		// from items
		if (plainSelect.getFromItem() != null) {
			Node from = new Node("from", NodeType.FROM_ITEM);
			Node fromItem = plainSelect.getFromItem().nodeAccept(this);
			from.addChild(fromItem);
			node.addChild(from);

			// join
			List joins = plainSelect.getJoins();
			if (joins != null) {
				Iterator it = joins.iterator();
				while (it.hasNext()) {
					Join join = (Join) it.next();
					from.addChild(join.getRightItem().nodeAccept(this));
				}
			}
		}

		if (plainSelect.getWhere() != null) {
			Node where = new Node("where", NodeType.WHERE_CLAUSE);
			Node expression = plainSelect.getWhere().nodeAccept(this);
			where.addChild(expression);
			node.addChild(where);
		}

		if (plainSelect.getGroupByColumnReferences() != null) {
			Node groupBy = new Node("groupBy", NodeType.GROUPBY);
			List grps = plainSelect.getGroupByColumnReferences();
			for (int i = 0; i < grps.size(); i++) {
				groupBy.addChild(((Expression) grps.get(i)).nodeAccept(this));
			}
			node.addChild(groupBy);
		}

		if (plainSelect.getHaving() != null) {
			Node having = new Node("having", NodeType.HAVING);
			having.addChild(plainSelect.getHaving().nodeAccept(this));
			node.addChild(having);
		}

		if (plainSelect.getOrderByElements() != null) {
			Node orderBy = new Node("orderBy", NodeType.ORDERBY);
			List orders = plainSelect.getOrderByElements();
			for (int i = 0; i < orders.size(); i++) {
				OrderByElement orderByele = (OrderByElement) orders.get(i);
				orderBy.addChild(orderByele.nodeAccept(this));
			}
			node.addChild(orderBy);
		}

		if (plainSelect.getLimit() != null) {
			Limit lt = plainSelect.getLimit();
			Node limit = new Node(lt.toString(), NodeType.LIMIT);
			node.addChild(limit);

		}

		return node;
	}

	// not all right
	@Override
	public Node nodeVisit(Union union) {
		// TODO Auto-generated method stub
		String unionString = union.isAll() ? "union all" : "union distinct";
		Node node = new Node(unionString, NodeType.UNION);
		List ps = union.getPlainSelects();
		for (int i = 0; i < ps.size(); i++) {
			PlainSelect p = (PlainSelect) ps.get(i);
			node.addChild(p.nodeAccept(this));
		}
		if (union.getOrderByElements() != null) {
			Node orderBy = new Node("orderBy", NodeType.ORDERBY);
			List orders = union.getOrderByElements();
			for (int i = 0; i < orders.size(); i++) {
				OrderByElement orderByele = (OrderByElement) orders.get(i);
				orderBy.addChild(orderByele.nodeAccept(this));
			}
			node.addChild(orderBy);
		}
		node.addChild(node);

		if (union.getLimit() != null) {
			Limit lt = union.getLimit();
			Node limit = new Node(lt.toString(), NodeType.LIMIT);
			node.addChild(limit);

		}
		return node;
	}

	@Override
	public Node nodeVisit(OrderByElement orderBy) {
		// TODO Auto-generated method stub
		Node obe = new Node(orderBy.isAsc() ? "asc" : "dest",
				NodeType.ORDERBYELE);
		obe.addChild(orderBy.getExpression().nodeAccept(this));
		return obe;
	}

}
